
package com.zdkj.subway.stm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdkj.common.security.util.ObjectUtils;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.stm.dto.in.SwStTicketCheckCheckDTO;
import com.zdkj.subway.stm.dto.in.SwStTicketCheckDTO;
import com.zdkj.subway.stm.entity.*;
import com.zdkj.subway.stm.mapper.SwStTicketCheckMapper;
import com.zdkj.subway.stm.service.*;
import com.zdkj.subway.stm.util.BeanUtilsStm;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 车票盘点数据
 *
 * @author songtuo
 * @date 2020-07-11 22:08:18
 */
@Service
public class SwStTicketCheckServiceImpl extends ServiceImpl<SwStTicketCheckMapper, SwStTicketCheck> implements SwStTicketCheckService {
    @Autowired
    SwStTicketCheckGeneralService generalService;

    @Autowired
    SwStTicketCheckMarketingService marketingService;

    @Autowired
    SwStTicketCheckOnewayPressureService pressureService;

    @Autowired
    SwStTicketCheckWorkCardService workCardService;

    @Autowired
    SwStTicketCheckOnewayService onewayService;

    /**
     * 车票异常通知
     *
     * @param swStTicketCheckDTO
     * @return
     */
    @Autowired
    SwStTicketsInventoryAbnormalNoticeService noticeService;

    @Override
    public boolean saveSwStTicketCheck(SwStTicketCheckDTO swStTicketCheckDTO) {
        //1:主表属性复制
        SwStTicketCheck ticketCheck = swStTicketCheckDTO.getTicketCheck();
        SwStTicketCheck ticketCheckObj = ObjectUtils.getDefaultObj(SwStTicketCheck.class);
        BeanUtil.copyProperties(ticketCheckObj, ticketCheck, CopyOptions.create().setIgnoreNullValue(true));
        //2020.10.19增加设置客运值班员
        ticketCheck.setWorkPersonName(SecurityUtils.getUser().getNikeName());
        ticketCheck.setWorkPersonJobNo(SecurityUtils.getUser().getUserCode());
        ticketCheck.setWorkPersonId(SecurityUtils.getUser().getId());
        //2:从表属性复制
        List<SwStTicketCheckGeneral> checkGenerals = swStTicketCheckDTO.getCheckGenerals();
        BeanUtilsStm.buildProperties(checkGenerals);
        List<SwStTicketCheckMarketing> checkMarketings = swStTicketCheckDTO.getCheckMarketings();
        BeanUtilsStm.buildProperties(checkMarketings);
        List<SwStTicketCheckOnewayPressure> checkOnewayPressures = swStTicketCheckDTO.getCheckOnewayPressures();
        BeanUtilsStm.buildProperties(checkOnewayPressures);
        List<SwStTicketCheckOneway> checkOneways = swStTicketCheckDTO.getCheckOneways();
        BeanUtilsStm.buildProperties(checkOneways);
        List<SwStTicketCheckWorkCard> workCards = swStTicketCheckDTO.getWorkCards();
        BeanUtilsStm.buildProperties(workCards);
        countTicketNum(ticketCheck, checkGenerals, checkMarketings, checkOnewayPressures, checkOneways);
        //3:保存主表
        save(ticketCheck);
        //4:保存从表
        saveSunData(ticketCheck, checkGenerals, checkMarketings, checkOnewayPressures, checkOneways, workCards);
        return true;
    }

    /**
     * 保存字表
     *
     * @param ticketCheck
     * @param checkGenerals
     * @param checkMarketings
     * @param checkOnewayPressures
     * @param checkOneways
     * @param workCards
     */
    private void saveSunData(SwStTicketCheck ticketCheck, List<SwStTicketCheckGeneral> checkGenerals, List<SwStTicketCheckMarketing> checkMarketings, List<SwStTicketCheckOnewayPressure> checkOnewayPressures, List<SwStTicketCheckOneway> checkOneways, List<SwStTicketCheckWorkCard> workCards) {
        Integer rid = ticketCheck.getId();
        if (CollectionUtil.isNotEmpty(checkGenerals)) {
            checkGenerals.forEach(x -> x.setRelationId(rid));
            generalService.saveBatch(checkGenerals);
        }
        if (CollectionUtil.isNotEmpty(checkMarketings)) {
            checkMarketings.forEach(x -> x.setRelationId(rid));
            marketingService.saveBatch(checkMarketings);
        }
        if (CollectionUtil.isNotEmpty(checkOnewayPressures)) {
            checkOnewayPressures.forEach(x -> x.setRelationId(rid));
            pressureService.saveBatch(checkOnewayPressures);
        }
        if (CollectionUtil.isNotEmpty(workCards)) {
            workCards.forEach(x -> x.setRelationId(rid));
            workCardService.saveBatch(workCards);
        }
        if (CollectionUtil.isNotEmpty(checkOneways)) {
            checkOneways.forEach(x -> x.setRelationId(rid));
            onewayService.saveBatch(checkOneways);
        }
    }

    /**
     * 统计票数量
     *
     * @param ticketCheck
     * @param checkGenerals
     * @param checkMarketings
     * @param checkOnewayPressures
     * @param checkOneways
     */
    private void countTicketNum(SwStTicketCheck ticketCheck, List<SwStTicketCheckGeneral> checkGenerals, List<SwStTicketCheckMarketing> checkMarketings, List<SwStTicketCheckOnewayPressure> checkOnewayPressures, List<SwStTicketCheckOneway> checkOneways) {
        //3:计算单程票实际盘点数量  计算单程票结存 TODO 计算公式  如果是null 默认0 否则重新计算
        Integer realCheckNumber = 0;
        if (CollectionUtil.isNotEmpty(checkOneways)) {
            for (SwStTicketCheckOneway checkOneway : checkOneways) {
                Integer onyWayRealNum = checkOneway.getRealCheckNumber();
                if (null != onyWayRealNum) {
                    realCheckNumber = realCheckNumber + onyWayRealNum;
                }
            }
        }
        ticketCheck.setRealCheckNumber(realCheckNumber);

        //4:单程票压票 如果是null 默认0 否则重新计算
        Integer pressureNumber = 0;
        if (CollectionUtil.isNotEmpty(checkOnewayPressures)) {
            for (SwStTicketCheckOnewayPressure checkOnewayPressure : checkOnewayPressures) {
                Integer realCheckNumberPressure = checkOnewayPressure.getRealCheckNumber();
                if (null != realCheckNumber) {
                    pressureNumber = realCheckNumberPressure + pressureNumber;
                }
            }
        }
        ticketCheck.setPressureNumber(pressureNumber);

        //5: 预支单程票 应急纸票合计  0预置单程票  1是应急车票
        //预支单程票
        Integer prefabricatedTicket = 0;
        //应急纸票
        Integer emergencyPaperTicket = 0;
        if (CollectionUtil.isNotEmpty(checkGenerals)) {
            for (SwStTicketCheckGeneral checkGeneral : checkGenerals) {
                if (checkGeneral.getTicketType().equals(0)) {
                    if (checkGeneral.getTicketNum() != null) {
                        prefabricatedTicket = checkGeneral.getTicketNum() + prefabricatedTicket;
                    }
                }
                if (checkGeneral.getTicketType().equals(1)) {
                    if (checkGeneral.getTicketNum() != null) {
                        emergencyPaperTicket = checkGeneral.getTicketNum() + emergencyPaperTicket;
                    }
                }
            }
        }
        ticketCheck.setPrefabricatedTicket(prefabricatedTicket);
        ticketCheck.setEmergencyPaperTicket(emergencyPaperTicket);

        //6:营销车票设置 如果是null 默认0 否则重新计算
        Integer marketingNumber = 0;
        if (CollectionUtil.isNotEmpty(checkMarketings)) {
            for (SwStTicketCheckMarketing marketing : checkMarketings) {
                if (marketing.getTicketNum() != null) {
                    marketingNumber = marketing.getTicketNum() + marketingNumber;
                }
            }
        }
        ticketCheck.setMarketingNumber(marketingNumber);
    }

    /**
     * 更新过程中需要注意的是  新增删除更新 操作
     *
     * @param swStTicketCheckDTO
     * @return
     */
    @Override
    @Transactional
    public boolean updateSwStTicketCheck(SwStTicketCheckDTO swStTicketCheckDTO) {
        SwStTicketCheck ticketCheck = swStTicketCheckDTO.getTicketCheck();
        Integer rid = ticketCheck.getId();
        //更新单程票盘点
        List<SwStTicketCheckOneway> oneways = swStTicketCheckDTO.getCheckOneways();
        oneways.forEach(x -> x.setRelationId(rid));
        List<Integer> owids = oneways.stream().map(SwStTicketCheckOneway::getId).collect(Collectors.toList());
        List<SwStTicketCheckOneway> owlist = onewayService.list(new QueryWrapper<SwStTicketCheckOneway>().lambda().eq(SwStTicketCheckOneway::getRelationId, rid));
        List<Integer> oworginIds = owlist.stream().map(SwStTicketCheckOneway::getId).collect(Collectors.toList());
        Collection<Integer> owremoveIds = CollectionUtils.subtract(oworginIds, owids);
        if (CollectionUtils.isNotEmpty(oneways)) {
            onewayService.saveOrUpdateBatch(oneways);
        }
        if (CollectionUtils.isNotEmpty(owremoveIds)) {
            onewayService.removeByIds(owremoveIds);
        }
        //跟新单程票压票
        List<SwStTicketCheckOnewayPressure> onewayPressures=swStTicketCheckDTO.getCheckOnewayPressures();
        onewayPressures.forEach(x -> x.setRelationId(rid));
        List<Integer> owpids = onewayPressures.stream().map(SwStTicketCheckOnewayPressure::getId).collect(Collectors.toList());
        List<SwStTicketCheckOnewayPressure> owplist = pressureService.list(new QueryWrapper<SwStTicketCheckOnewayPressure>().lambda().eq(SwStTicketCheckOnewayPressure::getRelationId, rid));
        List<Integer> owporginIds = owplist.stream().map(SwStTicketCheckOnewayPressure::getId).collect(Collectors.toList());
        Collection<Integer> owpremoveIds = CollectionUtils.subtract(owporginIds, owpids);
        if (CollectionUtils.isNotEmpty(onewayPressures)) {
            pressureService.saveOrUpdateBatch(onewayPressures);
        }
        if (CollectionUtils.isNotEmpty(owpremoveIds)) {
            pressureService.removeByIds(owpremoveIds);
        }
        //更新营销车票
        List<SwStTicketCheckMarketing> checkMarketings = swStTicketCheckDTO.getCheckMarketings();
        checkMarketings.forEach(x -> x.setRelationId(rid));
        List<Integer> ids = checkMarketings.stream().map(SwStTicketCheckMarketing::getId).collect(Collectors.toList());
        List<SwStTicketCheckMarketing> list = marketingService.list(new QueryWrapper<SwStTicketCheckMarketing>().lambda().eq(SwStTicketCheckMarketing::getRelationId, rid));
        List<Integer> orginIds = list.stream().map(SwStTicketCheckMarketing::getId).collect(Collectors.toList());
        Collection<Integer> removeIds = CollectionUtils.subtract(orginIds, ids);
        if (CollectionUtils.isNotEmpty(checkMarketings)) {
            marketingService.saveOrUpdateBatch(checkMarketings);
        }
        if (CollectionUtils.isNotEmpty(removeIds)) {
            marketingService.removeByIds(removeIds);
        }
        //更新通用表
        List<SwStTicketCheckGeneral> checkGenerals = swStTicketCheckDTO.getCheckGenerals();
        checkGenerals.forEach(x -> x.setRelationId(rid));
        List<Integer> geneIds = checkGenerals.stream().map(SwStTicketCheckGeneral::getId).collect(Collectors.toList());
        List<SwStTicketCheckGeneral> geneList = generalService.list(new QueryWrapper<SwStTicketCheckGeneral>().lambda().eq(SwStTicketCheckGeneral::getRelationId, rid));
        List<Integer> orginGeneIds = geneList.stream().map(SwStTicketCheckGeneral::getId).collect(Collectors.toList());
        Collection<Integer> removeGeneIds = CollectionUtils.subtract(orginGeneIds, geneIds);
        if (CollectionUtils.isNotEmpty(checkGenerals)) {
            generalService.saveOrUpdateBatch(checkGenerals);
        }
        if (CollectionUtils.isNotEmpty(removeGeneIds)) {
            generalService.removeByIds(removeGeneIds);
        }
        //更新工作卡表
        List<SwStTicketCheckWorkCard> workCards = swStTicketCheckDTO.getWorkCards();
        workCards.forEach(x -> x.setRelationId(rid));
        List<Integer> wIds = workCards.stream().map(SwStTicketCheckWorkCard::getId).collect(Collectors.toList());
        List<SwStTicketCheckWorkCard> wList = workCardService.list(new QueryWrapper<SwStTicketCheckWorkCard>().lambda().eq(SwStTicketCheckWorkCard::getRelationId, rid));
        List<Integer> orginWIds = wList.stream().map(SwStTicketCheckWorkCard::getId).collect(Collectors.toList());
        Collection<Integer> removeWIds = CollectionUtils.subtract(orginWIds, wIds);
        if (CollectionUtils.isNotEmpty(workCards)) {
            workCardService.saveOrUpdateBatch(workCards);
        }
        if (CollectionUtils.isNotEmpty(removeWIds)) {
            workCardService.removeByIds(removeWIds);
        }
        //更新主表
        countTicketNum(ticketCheck, checkGenerals, checkMarketings, swStTicketCheckDTO.getCheckOnewayPressures(), swStTicketCheckDTO.getCheckOneways());
        updateById(ticketCheck);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteCascadeById(Integer id) {
        removeById(id);
        marketingService.remove(new QueryWrapper<SwStTicketCheckMarketing>().lambda().eq(SwStTicketCheckMarketing::getRelationId, id));
        generalService.remove(new QueryWrapper<SwStTicketCheckGeneral>().lambda().eq(SwStTicketCheckGeneral::getRelationId, id));
        pressureService.remove(new QueryWrapper<SwStTicketCheckOnewayPressure>().lambda().eq(SwStTicketCheckOnewayPressure::getRelationId, id));
        workCardService.remove(new QueryWrapper<SwStTicketCheckWorkCard>().lambda().eq(SwStTicketCheckWorkCard::getRelationId, id));
        onewayService.remove(new QueryWrapper<SwStTicketCheckOneway>().lambda().eq(SwStTicketCheckOneway::getRelationId, id));
        return true;
    }

    @Override
    public SwStTicketCheckDTO queryDetailsByid(Integer id) {
        SwStTicketCheckDTO swStTicketCheckDTO = new SwStTicketCheckDTO();
        SwStTicketCheck ticketCheck = getById(id);
        List<SwStTicketCheckMarketing> marketings = marketingService.list(new QueryWrapper<SwStTicketCheckMarketing>().lambda().eq(SwStTicketCheckMarketing::getRelationId, id));
        swStTicketCheckDTO.setCheckMarketings(marketings);
        List<SwStTicketCheckGeneral> checkGenerals = generalService.list(new QueryWrapper<SwStTicketCheckGeneral>().lambda().eq(SwStTicketCheckGeneral::getRelationId, id));
        swStTicketCheckDTO.setCheckGenerals(checkGenerals);
        List<SwStTicketCheckOnewayPressure> pressures = pressureService.list(new QueryWrapper<SwStTicketCheckOnewayPressure>().lambda().eq(SwStTicketCheckOnewayPressure::getRelationId, id));
        swStTicketCheckDTO.setCheckOnewayPressures(pressures);
        List<SwStTicketCheckWorkCard> checkWorkCards = workCardService.list(new QueryWrapper<SwStTicketCheckWorkCard>().lambda().eq(SwStTicketCheckWorkCard::getRelationId, id));
        swStTicketCheckDTO.setWorkCards(checkWorkCards);
        List<SwStTicketCheckOneway> onewayList = onewayService.list(new QueryWrapper<SwStTicketCheckOneway>().lambda().eq(SwStTicketCheckOneway::getRelationId, id));
        swStTicketCheckDTO.setCheckOneways(onewayList);
        swStTicketCheckDTO.setTicketCheck(ticketCheck);
        return swStTicketCheckDTO;
    }

    @Override
    public boolean updateApprovalStatus(List<Integer> ids, String status) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        List<SwStTicketCheck> updateData = new ArrayList<>();
        for (Integer id : ids) {
            SwStTicketCheck stTicketCheck = new SwStTicketCheck();
            stTicketCheck.setId(id);
            stTicketCheck.setStatus(status);
            updateData.add(stTicketCheck);
        }

        return updateBatchById(updateData);
    }

    /**
     * 车票盘点审核
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkStatus(SwStTicketCheckCheckDTO dto) {
        SwStTicketCheck stTicketCheck = new SwStTicketCheck();
        stTicketCheck.setAbnormalNotictContent(dto.getAbnormalNotictContent());
        stTicketCheck.setId(dto.getId());
        stTicketCheck.setStatus(dto.getStatus());
        stTicketCheck.setReviewPersonId(SecurityUtils.getUser().getId());
        stTicketCheck.setReviewPersonName(SecurityUtils.getUser().getNikeName());
        stTicketCheck.setReviewPersonJobNo(SecurityUtils.getUser().getUserCode());
        //同步车站车票异常通知
        if (dto.getStatus().equals("3")) {
            SwStTicketCheckDTO swStTicketCheckDTO = queryDetailsByid(dto.getId());
            SwStTicketsInventoryAbnormalNotice abnormalNotice = new SwStTicketsInventoryAbnormalNotice();
            List<SwStTicketCheckWorkCard> workCards = swStTicketCheckDTO.getWorkCards();
            //认证卡
            List<SwStTicketCheckWorkCard> authCardList = workCards.stream().filter(x -> x.getTicketType().equals("1")).collect(Collectors.toList());
            //特殊卡
            List<SwStTicketCheckWorkCard> specialWorkCards = workCards.stream().filter(x -> x.getTicketType().equals("0")).collect(Collectors.toList());
            List<SwStTicketCheckOnewayPressure> checkOnewayPressures = swStTicketCheckDTO.getCheckOnewayPressures();
            Integer totalPressureNum = 0;
            for (SwStTicketCheckOnewayPressure checkOnewayPressure : checkOnewayPressures) {
                Integer scCleanNumber = checkOnewayPressure.getScCleanNumber();
                Integer realCheckNumber = checkOnewayPressure.getRealCheckNumber();
                totalPressureNum = totalPressureNum + scCleanNumber + realCheckNumber;
            }
            List<SwStTicketCheckOneway> checkOneways = swStTicketCheckDTO.getCheckOneways();
            Integer totalOnyWayNum = 0;
            for (SwStTicketCheckOneway checkOneway : checkOneways) {
                Integer realCheckNumber = checkOneway.getRealCheckNumber();
                Integer scCleanNumber = checkOneway.getScCleanNumber();
                totalOnyWayNum = totalOnyWayNum + realCheckNumber + scCleanNumber;
            }
            List<SwStTicketCheckMarketing> checkMarketings = swStTicketCheckDTO.getCheckMarketings();
            int totalMaretingNum = 0;
            for (SwStTicketCheckMarketing ticketCheckMarketing : checkMarketings) {
                Integer ticketNum = ticketCheckMarketing.getTicketNum();
                totalMaretingNum = ticketNum + totalMaretingNum;
            }
            //同步车票异常通知
            SwStTicketsInventoryAbnormalNotice ticketsInventoryAbnormalNoticeObject = ObjectUtils.getDefaultObj(SwStTicketsInventoryAbnormalNotice.class);
            BeanUtil.copyProperties(ticketsInventoryAbnormalNoticeObject, abnormalNotice, CopyOptions.create().setIgnoreNullValue(true));

            SwStTicketCheck ticketCheck = swStTicketCheckDTO.getTicketCheck();
            SwStTicketsInventoryAbnormalNotice notice= new SwStTicketsInventoryAbnormalNotice();
            notice.setLineCode(ticketCheck.getLineCode());
            notice.setStationCode(ticketCheck.getStationCode());

            abnormalNotice.setInventoryTime(ticketCheck.getCheckTime().toLocalDate());
            abnormalNotice.setAuthCardsNumber(authCardList.size());
            abnormalNotice.setSpecialWorkCardsNumber(specialWorkCards.size());
            abnormalNotice.setActualCountPressuerTickets(totalPressureNum);
            abnormalNotice.setActualCountOnewayTickets(totalOnyWayNum);
            abnormalNotice.setMarketCardsNumber(totalMaretingNum);
            abnormalNotice.setDifferenceReason(dto.getAbnormalNotictContent());
            noticeService.save(abnormalNotice);
            notice.setId(abnormalNotice.getId());
            noticeService.updateById(notice);// TODO 处理线路站点存不进去
        }


        return updateById(stTicketCheck);
    }
}
